package com.yungu.swift.assets.driver.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.yungu.swift.assets.config.ApplicationConfig;
import com.yungu.swift.assets.driver.dao.*;
import com.yungu.swift.assets.driver.enums.DriverErrorEnum;
import com.yungu.swift.assets.driver.model.dto.*;
import com.yungu.swift.assets.driver.model.param.*;
import com.yungu.swift.assets.driver.model.vo.*;
import com.yungu.swift.assets.driver.service.*;
import com.yungu.swift.assets.utils.DriverUniqueIdUtils;
import com.yungu.swift.assets.utils.PinyinUtils;
import com.yungu.swift.assets.utils.SendMessageUtils;
import com.yungu.swift.autoconfig.lock.RedisLock;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.model.PageVo;
import com.yungu.swift.base.model.config.DriverConfig;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.common.model.dto.CommonEvaluateCountDto;
import com.yungu.swift.common.service.CommonEvaluateCountService;
import com.yungu.swift.common.service.CommonSmsService;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.DriverConstant;
import com.yungu.swift.constants.MagicConstant;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.model.dto.OrderDto;
import com.yungu.swift.order.service.OrderComplainService;
import com.yungu.swift.order.service.OrderRiskControlService;
import com.yungu.swift.order.service.OrderService;
import com.yungu.swift.order.service.OrderTrackMileageService;
import com.yungu.swift.socket.communication.message.UploadLocationMessage;
import com.yungu.swift.socket.communication.service.UploadLocationService;
import com.yungu.swift.socket.push.model.PushContent;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.system.sys.model.dto.SysAccountDriverDto;
import com.yungu.swift.system.sys.model.dto.SysCompanyDto;
import com.yungu.swift.system.sys.service.SysAccountDriverService;
import com.yungu.swift.system.sys.service.SysCompanyService;
import com.yungu.swift.utils.*;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * 司机业务逻辑接口实现类
 *
 * @author cuixiuyin - Generate
 * @version 1.1.1-SNAPSHOT
 * @since 2018-07-05 16:23
 */
@Service
public class DriverServiceImpl extends BaseServiceImpl<DriverDto> implements DriverService {

    private static final Logger logger = LoggerFactory.getLogger(DriverServiceImpl.class);

    @Autowired
    private DriverMapper driverMapper;
    @Autowired
    private DriverCheckMapper driverCheckMapper;
    @Autowired
    private DriverTrainMapper driverTrainMapper;
    @Autowired
    private DriverLogMapper driverLogMapper;
    @Autowired
    private DriverSignLogMapper driverSignLogMapper;
    @Autowired
    private CarService carService;
    @Autowired
    private CarModelService carModelService;
    @Autowired
    private DriverPunishLogService driverPunishLogService;
    @Autowired
    private DriverStatusCycleService driverStatusCycleService;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private RedisLock redisLock;
    @Autowired
    private DriverCommissionConfigMapper driverCommissionConfigMapper;
    @Autowired
    private DriverQueueMapper driverQueueMapper;

    @Reference
    private OrderService orderService;
    @Reference
    private OrderComplainService orderComplainService;
    @Reference
    private OrderTrackMileageService orderTrackMileageService;
    @Reference
    private OrderRiskControlService orderRiskControlService;
    @Reference
    private CommonEvaluateCountService commonEvaluateCountService;
    @Reference
    private LocationService locationService;
    @Reference
    private CommonSmsService commonSmsService;
    @Reference
    private UploadLocationService uploadLocationService;
    @Reference
    private PushService pushService;
    @Reference
    private SysAccountDriverService sysAccountDriverService;
    @Reference
    private SysCompanyService sysCompanyService;

    @Override
    protected IMapper<DriverDto> getMapper() {
        return driverMapper;
    }

    private String UPDATE_ADDRESS_KEY = "UPDATE_ADDRESS_KEY_";

    @Override
    public ResponseData<PageVo<AdminDriverVo>> queryPageAdmin(AdminDriverPageParam driverPageParam) {
        PageBounds pageBounds = new PageBounds(driverPageParam.getPageNum(), driverPageParam.getPageSize());
        PageList<AdminDriverVo> pageList = driverMapper.queryPageAdmin(MapUtils.convertObjToMap(driverPageParam), pageBounds);
        PageVo<AdminDriverVo> pageVo = new PageVo(driverPageParam.getPageNum(), driverPageParam.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<List<DriverExportVo>> exportAdmin(AdminDriverPageParam driverPageParam) {
        return ResponseData.buildSuccessResponse(this.driverMapper.exportAdmin(MapUtils.convertObjToMap(driverPageParam)));
    }

    @Override
    public ResponseData<Integer> getCountAdmin(String appid, String agentUuid, String companyUuid) {
        Map<String, Object> objectMap = MapUtils.build(8);
        objectMap.put("appid", appid);
        objectMap.put("agentUuid", agentUuid);
        objectMap.put("companyUuid", companyUuid);
        return ResponseData.buildSuccessResponse(this.driverMapper.getCountAdmin(objectMap));
    }

    @Override
    public ResponseData<Integer> getOrderCount(String appid, String agentUuid, String companyUuid) {
        Map<String, Object> params = MapUtils.build(8);
        params.put("appid", appid);
        params.put("agentUuid", agentUuid);
        params.put("companyUuid", companyUuid);
        return ResponseData.buildSuccessResponse(this.driverMapper.getOrderCount(params));
    }

    @Override
    public ResponseData<DriverVo> selInfo(String uuid) {
        DriverVo driverVo = driverMapper.selInfoByTokenOrId(MapUtils.build("uuid", uuid));
        if (driverVo != null) {
            fillInfo(driverVo);
        }
        return ResponseData.buildSuccessResponse(driverVo);
    }

    /**
     * 补充司机提现信息
     *
     * @param driverVo
     */
    private void fillInfo(DriverVo driverVo) {
        // 从系统获取可提现时间
        driverVo.setCanWishdraw(0);
        driverVo.setPoundageTitle("");

        DriverConfig.SidebarBean.Sidebar sidebar = getSidebarInfo(driverVo.getBusinessType());
        List<Integer> withdrawalPeriod = sidebar.getWithdrawalPeriod();
        if (CollectionUtils.isNotEmpty(withdrawalPeriod) && withdrawalPeriod.size() != MagicConstant.INT_SEVEN) {
            driverVo.setCanWishdraw(1);
            StringBuilder sBuilder = new StringBuilder("每");
            for (Integer withdrawal : withdrawalPeriod.stream().sorted().collect(Collectors.toList())) {
                switch (withdrawal) {
                    case 1:
                        sBuilder.append("周一");
                        break;
                    case 2:
                        sBuilder.append("周二");
                        break;
                    case 3:
                        sBuilder.append("周三");
                        break;
                    case 4:
                        sBuilder.append("周四");
                        break;
                    case 5:
                        sBuilder.append("周五");
                        break;
                    case 6:
                        sBuilder.append("周六");
                        break;
                    case 7:
                        sBuilder.append("周日");
                        break;
                    default:
                        break;
                }
            }
            sBuilder.append("可申请提现");
            driverVo.setPoundageTitle(sBuilder.toString());
        }
        if (CollectionUtils.isNotEmpty(withdrawalPeriod) && withdrawalPeriod.size() == MagicConstant.INT_SEVEN && driverVo.getBalance() > 0) {
            driverVo.setCanWishdraw(1);
            driverVo.setPoundageTitle("全周都可申请提现");
        }
    }

    private DriverConfig.SidebarBean.Sidebar getSidebarInfo(Integer type) {
        DriverConfig.SidebarBean sidebar = ApplicationConfig.DRIVER_CONFIG.getSidebar();
        switch (type) {
            case CommonConstant.BUSINESS_TYPE_TAXI:
                return sidebar.getTaxi();
            case CommonConstant.BUSINESS_TYPE_SPEC:
                return sidebar.getSpecial();
            case CommonConstant.BUSINESS_TYPE_POOL:
                return sidebar.getJoin();
            case CommonConstant.BUSINESS_TYPE_EXPRESS:
                return sidebar.getExpress();
            default:
                break;
        }
        return new DriverConfig.SidebarBean.Sidebar();
    }

    @Override
    public ResponseData<List<DriverDto>> listExtend(Map<String, Object> paramsMap) {
        List<DriverDto> driverDtos = driverMapper.listExtend(paramsMap);
        if (CollectionUtils.isNotEmpty(driverDtos)) {
            for (DriverDto driverDto : driverDtos) {
                driverDto.setDriverTrainDtoList(driverTrainMapper.list(MapUtils.build("driverUuid", driverDto.getUuid())));
            }
        }
        return ResponseData.buildSuccessResponse(driverDtos);
    }

    @Override
    @Transactional
    public ResponseData<Boolean> add(DriverDto driverDto) {
        //司机信息
        String uuid = StringUtils.buildUUID();
        driverDto.setUuid(uuid);
        driverDto.setPassword(Md5Utils.encode("123456"));
        driverDto.setIsWork(DriverConstant.DRIVER_IS_NOT_WORK);
        driverDto.setStatus(DriverConstant.DRIVER_STATUS_NORMAL);
        driverDto.setIsFirst(DriverConstant.IS_FIRST);
        //1：全部
        driverDto.setRemindType(DriverConstant.DRIVER_REMIND_TYPE_ALL);
        //余额
        driverDto.setBalance(0d);
        driverDto.setOrderCount(0);
        driverDto.setPushLevel(1);
        driverDto.setVersion(0);
        // 设置未激活状态
        driverDto.setActive(0);
        // 设置唯一编号
        driverDto.setDriverUniqueId(DriverUniqueIdUtils.getDriverUniqueId(driverDto.getCityUuid()));
        driverMapper.add(driverDto);
        //同步司机账号
        SysAccountDriverDto accountDriverDto = new SysAccountDriverDto();
        accountDriverDto.setUuid(uuid);
        accountDriverDto.setAppid(driverDto.getAppid());
        accountDriverDto.setAccountName(driverDto.getName());
        accountDriverDto.setFrozenBalance(BigDecimal.ZERO);
        accountDriverDto.setCanFrowardBalance(BigDecimal.ZERO);
        accountDriverDto.setFrowardAccumulate(BigDecimal.ZERO);
        accountDriverDto.setAlipayAccumulate(BigDecimal.ZERO);
        accountDriverDto.setTenpayAccumulate(BigDecimal.ZERO);
        accountDriverDto.setCreateOn(new Date());
        sysAccountDriverService.add(accountDriverDto);
        //培训信息处理 —— 先删后增
        List<DriverTrainDto> driverTrainDtoList = driverDto.getDriverTrainDtoList();
        if (driverTrainDtoList != null && driverTrainDtoList.size() > 0) {
            //移除旧培训信息
            driverTrainMapper.delByDriver(driverDto.getUuid());
            //设置新培训信息
            for (DriverTrainDto driverTrainDto : driverTrainDtoList) {
                driverTrainDto.setUuid(StringUtils.buildUUID());
                driverTrainDto.setDriverUuid(driverDto.getUuid());
                driverTrainDto.setLicenseId(driverDto.getLicenseId());
                driverTrainDto.setCreateBy(driverDto.getCreateBy());
                driverTrainDto.setCreateOn(new Date());
            }
            driverTrainMapper.addBatch(driverTrainDtoList);
        }
        //新增时发送短信
        SendMessageUtils.driverAddSend(commonSmsService, driverDto, getDriverServiceTel(driverDto.getUuid(),
                driverDto.getCompanyUuid()).getData());
        return ResponseData.buildSuccessResponse("操作成功，司机信息已保存！", Boolean.TRUE);
    }


    @Override
    public ResponseData<DriverVo> login(DriverDto driverParam, DriverLogDto driverLogParam) {
        // 通过手机号码及司机类型检索
        Map<String, Object> map = MapUtils.build(4);
        map.put("mobile", driverParam.getMobile());
        map.put("appid", driverParam.getAppid());
        map.put("dimissionStatus", DriverConstant.DRIVER_STATUS_DIMISSION);
        List<DriverDto> drivers = driverMapper.list(map);
        String errorMsg = "未找到司机账号，请检查手机号是否正确";
        if (CollectionUtils.isEmpty(drivers)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, errorMsg);
        }
        DriverDto driverDto = drivers.get(0);
        //这边先校验是否在1小时内错误达到5次
        String loginCountCache = "LOGIN_COUNT" + driverDto.getUuid();
        Object obj = redisCacheService.get(loginCountCache);
        if (obj != null && (Integer) obj >= 5) {
            String timeStr = DateUtils.getTimeStr(driverDto.getCacheLoginTime().getTime() - System.currentTimeMillis() + 3600000L);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "您当前登录错误次数已超过5次，请在" + timeStr + "之后重新登录！");
        }
        //补充司机设备信息
        supervisionCheck(driverDto, driverParam);
        // 检查司机账号密码是否正确
        if (!driverDto.getPassword().equalsIgnoreCase(Md5Utils.encode(driverParam.getPassword()))) {
            DriverDto errorCountDto = new DriverDto();
            errorCountDto.setUuid(driverDto.getUuid());
            // 判断是否在三分钟内
//            Date loginTime = driverDto.getCacheLoginTime();
//            if (loginTime != null && loginTime.getTime() + 180000L < System.currentTimeMillis()) {
//                errorCountDto.setCacheLoginTime(new Date());
//                redisCacheService.delete(loginCountCache);
//            } else {
//                errorCountDto.setCacheLoginTime(new Date());
//                redisCacheService.set(loginCountCache, obj == null ? 1 : (Integer) obj + 1, 60L);
//            }
            errorCountDto.setCacheLoginTime(new Date());
            redisCacheService.set(loginCountCache, obj == null ? 1 : (Integer) obj + 1, 60L);
            driverMapper.edit(errorCountDto);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "密码错误，您已输错" + (obj == null ? 1 : (Integer) obj + 1) + "次，3分钟内连续输错5次密码将在1个小时内无法登录");
        } else {
            redisCacheService.delete(loginCountCache);
        }
        // 检查司机的公司是否存在
        if (StringUtils.isEmpty(driverDto.getCompanyUuid())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "错误！司机没有公司信息");
        }
        Date date = new Date();
        // 检查司机状态是否可用
        if (!driverDto.getStatus().equals(DriverConstant.DRIVER_STATUS_NORMAL)) {
            String msg;
            switch (driverDto.getStatus()) {
                case DriverConstant.DRIVER_STATUS_SHORT_CLOSE:
                    long abortTime = driverDto.getAbortTime() == null ? date.getTime() : driverDto.getAbortTime().getTime();
                    if (date.getTime() >= abortTime) {
                        driverDto.setStatus(DriverConstant.DRIVER_STATUS_NORMAL);
                        break;
                    } else {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String abortTimeStr = sdf.format(driverDto.getAbortTime());
                        msg = "您的账号已被封，原因是：" + driverDto.getAbortRemark() + "，解封日期：" + abortTimeStr + "。如有疑问请联系客服";
                        return ResponseData.buildErrorResponse(DriverErrorEnum.STATUS_INVALID.getCode(), msg);
                    }
                case DriverConstant.DRIVER_STATUS_LONG_CLOSE:
                    msg = "您的账号已被封，原因是：" + driverDto.getAbortRemark() + "。如有疑问请联系客服";
                    return ResponseData.buildErrorResponse(DriverErrorEnum.STATUS_INVALID.getCode(), msg);
                case DriverConstant.DRIVER_STATUS_UNVERIFIED:
                    return ResponseData.buildErrorResponse(DriverErrorEnum.STATUS_INVALID.getCode(), "该账号尚未审核");
                default:
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "该账号不存在");
            }
        }
        //生成token
        driverDto.setToken(StringUtils.buildUUID());
        // 司机log为插入型，只新增记录
        driverLogParam.setUuid(StringUtils.buildUUID());
        driverLogParam.setDriverUuid(driverDto.getUuid());
        driverLogParam.setCreateOn(new Date());
        driverLogMapper.add(driverLogParam);
        CompletableFuture.runAsync(() -> redisCacheService.delete(loginCountCache));
        // 检索返回数据
        DriverVo driverVo = driverMapper.selInfoByTokenOrId(MapUtils.build("uuid", driverDto.getUuid()));
        driverVo.setToken(driverDto.getToken());
        // 司机客服电话做降级处理
        if (StringUtils.isEmpty(driverVo.getServiceTel()) && CommonConstant.BUSINESS_TYPE_POOL == driverVo.getBusinessType()) {
            driverVo.setServiceTel(ApplicationConfig.SERVER_CONFIG.getSystem().getJoinServiceTel());
        }
        if (StringUtils.isEmpty(driverVo.getServiceTel()) && CommonConstant.BUSINESS_TYPE_POOL != driverVo.getBusinessType()) {
            driverVo.setServiceTel(ApplicationConfig.COMMON_CONFIG.getServiceTel());
        }
        //添加缓存
        updateCached(driverDto.getToken(), driverVo);
        driverDto.setUpdateOn(new Date());
        driverDto.setCacheLoginTime(null);
        driverDto.setLastLogin(new Date());
        driverMapper.edit(driverDto);
        return ResponseData.buildSuccessResponse("登录成功", driverVo);
    }

    /**
     * 监管平台字段判断：运营商，手版本，app版本更新时间
     *
     * @param driverDto
     * @param driverParam
     * @return
     */
    private void supervisionCheck(DriverDto driverDto, DriverDto driverParam) {
        String netType = ValidateUtils.checkMobile(emptyDefault(driverParam.getMobile()));
        //给运营商赋值
        driverDto.setNetType(Integer.parseInt(netType));
        String netTypeTemp = ValidateUtils.checkMobile(emptyDefault(driverParam.getMobile()));
        String deviceVersion = emptyDefault(driverDto.getDeviceVersion());
        String deviceVersionTemp = emptyDefault(driverParam.getDeviceVersion());
        String appVersion = emptyDefault(driverDto.getAppVersion());
        String appVersionTemp = emptyDefault(driverParam.getAppVersion());
        driverDto.setDeviceToken(driverParam.getDeviceToken());
        driverDto.setDeviceType(driverParam.getDeviceType());
        driverDto.setDeviceVersion(driverParam.getDeviceVersion());
        driverDto.setAppVersion(driverParam.getAppVersion());
        if (!netType.equals(netTypeTemp) || !deviceVersion.equals(deviceVersionTemp) || !appVersion.equals(appVersionTemp)) {
            driverDto.setSupervisionUpdateTime(new Date());
        }
    }

    private String emptyDefault(String str) {
        return StringUtils.isEmpty(str) ? "" : str;
    }

    @Override
    @Transactional
    public ResponseData<Boolean> edit(DriverDto driverDto) {
        //培训信息处理
        List<DriverTrainDto> driverTrainDtoList = driverDto.getDriverTrainDtoList();
        if (driverTrainDtoList != null && driverTrainDtoList.size() > 0) {
            //设置新培训信息
            for (DriverTrainDto driverTrainDto : driverTrainDtoList) {
                if (StringUtils.isNotEmpty(driverTrainDto.getUuid())) {
                    driverTrainDto.setUpdateOn(new Date());
                    driverTrainDto.setUpdateBy(driverDto.getUpdateBy());
                    driverTrainMapper.edit(driverTrainDto);
                } else {
                    driverTrainDto.setUuid(StringUtils.buildUUID());
                    driverTrainDto.setCreateOn(new Date());
                    driverTrainDto.setCreateBy(driverDto.getUpdateBy());
                    driverTrainDto.setDriverUuid(driverDto.getUuid());
                    driverTrainMapper.add(driverTrainDto);
                }
            }
        }
        //通过更新条数来判断是否更新成功
        if (driverMapper.edit(driverDto) > 0) {
            return ResponseData.buildSuccessResponse("操作成功，司机信息已保存！", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机信息更新失败");
    }

    @Override
    public ResponseData<List<CarDto>> bindCarList(AdminDriverBindCarParam bindCarParam) {
        DriverDto driverDto = driverMapper.get(bindCarParam.getUuid());
        if (driverDto != null) {
            Map<String, Object> build = MapUtils.build(4);
            build.put("agentUuid", driverDto.getAgentUuid());
            build.put("companyUuid", driverDto.getCompanyUuid());
            build.put("businessType", driverDto.getBusinessType());
            build.put("plateNum", bindCarParam.getPlateNum());
            return carService.plateNumSearch(build);
        }
        return ResponseData.buildSuccessResponse(Lists.newArrayList());
    }

    @Override
    public ResponseData<Boolean> bindCar(AdminDriverBindCarParam bindCarParam) {
        DriverDto driverDto = driverMapper.get(bindCarParam.getUuid());
        if (null == driverDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机信息失败");
        }
        ResponseData<List<CarDto>> responseData = carService.list(MapUtils.build("plateNum", bindCarParam.getPlateNum()));
        if (!responseData.isSuccess() || responseData.getData() == null || CollectionUtils.isEmpty(responseData.getData())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取车辆信息失败");
        }
        CarDto carDto = responseData.getData().get(0);
        ResponseData<CarModelDto> getCarMoel = carModelService.get(carDto.getCarModelUuid());
        if (getCarMoel.isSuccess() && getCarMoel.getData() != null && !getCarMoel.getData().getBusinessType().equals(driverDto.getBusinessType())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "绑定失败：车辆类型与司机业务类型不匹配");
        }
        driverDto.setCarUuid(carDto.getUuid());
        driverDto.setUpdateBy(bindCarParam.getUserUuid());
        driverMapper.edit(driverDto);
        //短信通知
        SendMessageUtils.bingCarSend(commonSmsService, driverDto.getMobile(), driverDto.getAppid());
        return ResponseData.buildSuccessResponse(driverDto.getName() + "司机和" + carDto.getPlateNum() + "车辆已绑定，已发送短信告知该司机。司机登录手机号，即可出车接单绑定车辆成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> logout(String token, String appid, Double offWorkLng, Double offWorkLat, String uploadText) {
        //清除缓存
        redisCacheService.delete(token);
        //清除token
        Map<String, Object> map = MapUtils.build(4);
        map.put("token", token);
        map.put("appid", appid);
        List<DriverDto> drivers = driverMapper.list(map);
        //不能全字段更改
        if (CollectionUtils.isNotEmpty(drivers)) {
            DriverDto driver = drivers.get(0);
            //清除缓存
            redisCacheService.delete(driver.getUuid());
            redisCacheService.delete(driver.getToken());
            DriverDto editDriver = new DriverDto();
            editDriver.setUuid(driver.getUuid());
            editDriver.setToken("");
            driverMapper.edit(editDriver);
            //如果登出时未收车，则执行收车操作
            if (!DriverConstant.DRIVER_IS_NOT_WORK.equals(driver.getIsWork())) {
                ResponseData<Boolean> responseData = offWork(driver.getUuid(), offWorkLng, offWorkLat, uploadText);
                if (responseData.isSuccess()) {
                    return ResponseData.buildSuccessResponse("司机登出成功", Boolean.TRUE);
                }
                return ResponseData.buildSuccessResponse("司机登出失败，请重试", Boolean.FALSE);
            }
        }
        return ResponseData.buildSuccessResponse("司机登出成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> isDriver(String uuid, String token) {
        Map<String, Object> map = MapUtils.build(4);
        map.put("uuid", uuid);
        map.put("token", token);
        List<DriverDto> drivers = driverMapper.list(map);
        return ResponseData.buildSuccessResponse(CollectionUtils.isNotEmpty(drivers));
    }

    @Override
    public ResponseData<Map<String, String>> getDriverCachedByToken(String token) {
        Object object = redisCacheService.get(token);
        if (object != null) {
            return ResponseData.buildSuccessResponse((Map<String, String>) object);
        }
        DriverVo driver = driverMapper.selInfoByTokenOrId(MapUtils.build("token", token.trim()));
        //判断是否存取成功
        if (driver != null && StringUtils.isNotEmpty(driver.getUuid())) {
            Map<String, String> map = new HashMap<>(16);
            map.put("name", driver.getName());
            map.put("mobile", driver.getMobile());
            map.put("sex", driver.getSex() == null ? "" : driver.getSex().toString());
            map.put("face", driver.getFace());
            map.put("uuid", driver.getUuid());
            map.put("plateNum", driver.getPlateNum());
            map.put("companyName", driver.getShortName());
            map.put("status", String.valueOf(driver.getStatus()));
            map.put("type", String.valueOf(driver.getBusinessType()));
            map.put("agentUuid", driver.getAgentUuid());
            map.put("companyUuid", driver.getCompanyUuid());
            map.put("businessType", driver.getBusinessType() + "");
            return ResponseData.buildSuccessResponse(map);
        }
        return ResponseData.buildSuccessResponse(null);
    }

    private void updateCached(String token, DriverVo driver) {
        //判断是否存取成功
        if (driver != null && StringUtils.isNotEmpty(driver.getUuid())) {
            // 删除该司机原有的缓存记录（避免多点登陆的情况）
            Object oldToken = redisCacheService.get(driver.getUuid());
            if (oldToken != null) {
                redisCacheService.delete((String) oldToken);
            }
            Map<String, String> map = new HashMap<>(16);
            map.put("name", driver.getName());
            map.put("mobile", driver.getMobile());
            map.put("sex", driver.getSex() == null ? "" : driver.getSex().toString());
            map.put("face", driver.getFace());
            map.put("uuid", driver.getUuid());
            map.put("plateNum", driver.getPlateNum());
            map.put("companyName", driver.getShortName());
            map.put("status", String.valueOf(driver.getStatus()));
            map.put("type", String.valueOf(driver.getBusinessType()));
            map.put("agentUuid", driver.getAgentUuid());
            map.put("companyUuid", driver.getCompanyUuid());
            map.put("businessType", driver.getBusinessType() + "");
            redisCacheService.set(token, map);
            redisCacheService.set(driver.getUuid(), token);
        }
    }

    @Override
    public ResponseData<Boolean> onWork(String uuid, Double onWorkLng, Double onWorkLat, String uploadText) {
        DriverDto driverDto = driverMapper.get(uuid);
        if (StringUtils.isEmpty(driverDto.getCarUuid())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "您的账号还未绑定车辆！");
        }
        ResponseData<List<DriverDto>> responseData = findWorkedDrivers(driverDto.getCarUuid());
        if (responseData.isSuccess() && CollectionUtils.isNotEmpty(responseData.getData())) {
            DriverDto dto = responseData.getData().get(0);
            //司机的车辆被使用中
            if (uuid.equals(dto.getUuid())) {
                //司机自己已经出车
                DriverErrorEnum driverOnWork = DriverErrorEnum.DRIVER_ON_WORK;
                return ResponseData.buildErrorResponse(driverOnWork.getCode(), driverOnWork.getMsg());
            }
            //别的司机出车
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "同车其他司机已出车，司机名：" + dto.getName() + " ，手机号：" + dto.getMobile());
        }
        //这边根据参数给mongodb存点，先上传再出车收车
        UploadLocationMessage uploadLocationMessage = new Gson().fromJson(uploadText, UploadLocationMessage.class);
        ResponseData<Map<String, Object>> uploadResult = uploadLocationService.uploadDriverLocation(uploadLocationMessage);
        if (CommonConstant.BUSINESS_TYPE_POOL == driverDto.getBusinessType()) {
            return ResponseData.buildSuccessResponse("出车成功！", Boolean.TRUE);
        }
        if (uploadResult.isSuccess()) {
            DriverDto updDriverDto = new DriverDto();
            updDriverDto.setUuid(uuid);
            updDriverDto.setIsWork(DriverConstant.DRIVER_IS_WORK);
            driverMapper.edit(updDriverDto);
            //插入driver_sign_log表
            Date date = new Date();
            DriverSignLogDto driverSignLogDto = new DriverSignLogDto();
            driverSignLogDto.setUuid(StringUtils.buildUUID());
            driverSignLogDto.setCreateTime(date);
            driverSignLogDto.setDriverUuid(uuid);
            driverSignLogDto.setOnWorkTime(date);
            driverSignLogDto.setWorkday(date);
            driverSignLogDto.setOnWorkLng(onWorkLng);
            driverSignLogDto.setOnWorkLat(onWorkLat);
            driverSignLogMapper.add(driverSignLogDto);
            //这边将出车司机缓存进出车司机列表
            String onWorkLock = "onWorkLock";
            try {
                if (redisLock.lock(onWorkLock)) {
                    Object obj = redisCacheService.get(MagicConstant.PARAMS_ONWORK_DRIVER, false);
                    Set<String> onWorkSet = obj == null ? new HashSet<>() : (Set<String>) obj;
                    onWorkSet.add(uuid);
                    redisCacheService.set(MagicConstant.PARAMS_ONWORK_DRIVER, onWorkSet, false);
                }
            } catch (InterruptedException e) {
                logger.error("redisLock onWork InterruptedException driverUuid:{}", uuid, e);
            } finally {
                redisLock.unLock(onWorkLock);
            }
            // 调用订单服务 记录状态周期
            orderTrackMileageService.statusCycle(driverDto.getAppid(), driverDto.getUuid(), null, driverDto.getCarUuid(), DriverStatusCycleDto.ACTION_ON_WORK);
            return ResponseData.buildSuccessResponse("出车成功！", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "出车失败，请重试！");
    }

    @Override
    public ResponseData<Boolean> offWork(String driverUuid, Double offWorkLng, Double offWorkLat, String uploadText) {
//        DriverDto driverDto = driverMapper.list(MapUtils.build("uuid", driverUuid)).get(0);
        List<DriverDto> list = driverMapper.list(MapUtils.build("uuid", driverUuid));
        if (list.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机信息");
        }
        DriverDto driverDto = list.get(0);
        //已是下班状态
        if (DriverConstant.DRIVER_IS_NOT_WORK.equals(driverDto.getIsWork())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "已经是收车状态");
        }
        DriverSignLogDto driverSingLogDto = driverSignLogMapper.findOnWork(driverUuid);
        if (null == driverSingLogDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到出车信息");
        }
        //传点
        if (StringUtils.isNotEmpty(uploadText)) {
            Gson gson = new Gson();
            UploadLocationMessage uploadLocationMessage = gson.fromJson(uploadText, UploadLocationMessage.class);
            uploadLocationService.uploadDriverLocation(uploadLocationMessage);
        }
        try {
            DriverDto updDriverDto = new DriverDto();
            updDriverDto.setUuid(driverUuid);
            //下班
            updDriverDto.setIsWork(DriverConstant.DRIVER_IS_NOT_WORK);
            driverMapper.edit(updDriverDto);
            //跨城司机删除排队信息
            if (driverDto.getBusinessType() == CommonConstant.BUSINESS_TYPE_POOL) {
                driverQueueMapper.batchDelByDri(MapUtils.build("driUuid", driverUuid));
            }
            Map<String, Object> build = MapUtils.build(4);
            build.put("driverUuid", driverUuid);
            build.put("onWorkTime", driverSingLogDto.getOnWorkTime());
            build.put("offWorkTime", new Date());
            DriverSignLogDto updDriverSignLogDto = new DriverSignLogDto();
            updDriverSignLogDto.setUuid(driverSingLogDto.getUuid());
            //下班时间
            updDriverSignLogDto.setOffWorkTime(new Date());
            //订单总数
            updDriverSignLogDto.setOrderCount(orderService.getCount(build).getData());
            //投诉总数
            updDriverSignLogDto.setComplainCnt(orderComplainService.countDriComplain(build).getData());
            updDriverSignLogDto.setOffWorkLng(offWorkLng);
            updDriverSignLogDto.setOffWorkLat(offWorkLat);
            driverSignLogMapper.edit(updDriverSignLogDto);
            // 收车司机列表缓存缓存
            String offWorkLock = "offWorkLock";
            try {
                if (redisLock.lock(offWorkLock)) {
                    Object onWorkSet = redisCacheService.get(MagicConstant.PARAMS_ONWORK_DRIVER, false);
                    if (onWorkSet != null) {
                        ((Set<String>) onWorkSet).remove(driverUuid);
                        redisCacheService.set(MagicConstant.PARAMS_ONWORK_DRIVER, onWorkSet, false);
                    }
                }
            } catch (InterruptedException e) {
                logger.error("redisLock offWork InterruptedException driverUuid:{}", driverUuid, e);
            } finally {
                redisLock.unLock(offWorkLock);
            }
            // 调用订单服务 记录状态周期
            orderTrackMileageService.statusCycle(driverDto.getAppid(), driverDto.getUuid(), null, driverDto.getCarUuid(), DriverStatusCycleDto.ACTION_OFF_WORK);
        } catch (Exception e) {
            logger.error("DriverService offWork error.driverUuid:{}", driverUuid, e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "服务器异常，收车失败！");
        }
        return ResponseData.buildSuccessResponse("收车成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<List<DriverDto>> findWorkedDrivers(String carUuid) {
        return ResponseData.buildSuccessResponse(driverMapper.findWorkedDriverByCarNo(MapUtils.build("carUuid", carUuid)));
    }

    @Override
    public ResponseData<Boolean> resetPsw(String passWord, String uuid) {
        DriverDto driver = new DriverDto();
        driver.setUuid(uuid);
        driver.setPassword(Md5Utils.encode(passWord));
        driver.setIsFirst(DriverConstant.IS_NO_FIRST);
        driver.setResetPasswordTime(new Date());

        if (driverMapper.edit(driver) > 0) {
            return ResponseData.buildSuccessResponse("修改成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改失败");
    }

    @Override
    public ResponseData<Boolean> resetByPsw(String uuid, String oldPsw, String newPsw) {
//        DriverDto driver = driverMapper.list(MapUtils.build("uuid", uuid)).get(0);
        List<DriverDto> list = driverMapper.list(MapUtils.build("uuid", uuid));
        if (list.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到司机账号，请检查手机号是否正确");
        }
        DriverDto driver = list.get(0);
        if (driver == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到司机账号，请检查手机号是否正确");
        }
        if (!Md5Utils.encode(oldPsw).equals(driver.getPassword())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "旧密码错误");
        }
        driver.setPassword(Md5Utils.encode(newPsw));
        if (driverMapper.edit(driver) > 0) {
            return ResponseData.buildSuccessResponse("修改成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改失败");
    }

    @Override
    public ResponseData<Boolean> validate(String mobile, String idcard, String appid, Integer type) {
        Map<String, Object> map = MapUtils.build(8);
        map.put("mobile", mobile);
        map.put("appid", appid);
        map.put("idCard", idcard);
        map.put("dimission", DriverConstant.DRIVER_STATUS_DIMISSION);
        List<DriverDto> drivers = driverMapper.getValidDriver(map);
        if (null != drivers && drivers.size() > 0) {
            return ResponseData.buildSuccessResponse("验证通过", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "手机号和身份证号匹配失败或司机已离职");
    }


    @Override
    public ResponseData<Boolean> verifyIdentidy(String uuid, String password) {
        Map<String, Object> map = MapUtils.build(4);
        map.put("uuid", uuid);
        map.put("password", Md5Utils.encode(password));
        return ResponseData.buildSuccessResponse(CollectionUtils.isNotEmpty(driverMapper.list(map)));
    }

    @Override
    public ResponseData<Boolean> updDriverScore(String actualDriverUuid, Double score) {
        //根据实际接单司机获取司机信息
        List<DriverDto> driverDtoList = driverMapper.list(MapUtils.build("uuid", actualDriverUuid));
        if (CollectionUtils.isEmpty(driverDtoList)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机信息");
        }
        DriverDto driverDto = driverDtoList.get(0);
        DriverDto updDriverDto = new DriverDto();
        updDriverDto.setUuid(driverDto.getUuid());
        updDriverDto.setScore(score);
        return ResponseData.buildSuccessResponse(driverMapper.edit(updDriverDto) > 0);
    }

    @Override
    public ResponseData<Boolean> updRemind(DriverRemindParam driverRemindParam) {
        DriverDto driverDto = driverMapper.get(driverRemindParam.getUuid());
        DriverConfig.OrderBean.RemindTypeBean.RemindTypeItmeBean remindTypeItmeBean = getDriverRemindTypeBean(driverDto.getBusinessType());
        //修改地址次数限制暂时注释功能
//        String redisKey = UPDATE_ADDRESS_KEY+driverDto.getUuid();
//        boolean isUpdateAddress = false;
//        //如果修改了顺路地址 则记录修改次数 当天需要限制修改次数
//        if(!ParamUtil.defaultIfNull(driverRemindParam.getSameWayAddress(),"").equals(ParamUtil.defaultIfNull(driverDto.getSameWayAddress(),""))){
//            String updateCountStr = redisStringCacheService.get(redisKey);
//            Integer updateCount = StringUtils.isEmpty(updateCountStr)?0:Integer.parseInt(updateCountStr);
//            if(updateCount.equals(ParamUtil.defaultIfNull(remindTypeItmeBean.getSameWayEditAddressCount(),0))){
//                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "今日修改地址次数已用完！");
//            }
//            isUpdateAddress = true;
//        }
        //开启顺路模式 要求司机今日必须完成一单
        if (ParamUtil.defaultIfNull(driverRemindParam.getSameWayModel(), 0) == CommonConstant.SAME_WAY_MODEL_ON) {
            if (driverMapper.queryDriverTodayOrder(driverRemindParam.getUuid(), null) == 0) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "今日首单未完成，无法开启顺路模式");
            }
            //获取司机允许顺路模式次数
            Integer sameWayOrderCount = remindTypeItmeBean.getSameWayOrderCount();
            if (driverMapper.queryDriverTodayOrder(driverRemindParam.getUuid(), 1) >= sameWayOrderCount) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "今日顺路模式次数已用完！");
            }
        }

        //修改司机信息
        DriverDto driverParam = new DriverDto();
        BeanUtils.copyProperties(driverRemindParam, driverParam);
        driverParam.setUpdateBy(driverRemindParam.getUuid());
        driverParam.setUpdateOn(new Date());
        Integer successCount = driverMapper.edit(driverParam);
        if (successCount > 0) {
//            //修改成功 增加计数
//            if(isUpdateAddress){
//                redisStringCacheService.incr(redisKey);
//            }
            return ResponseData.buildSuccessResponse(true);
        }

        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "听单模式保存失败");
    }

    @Transactional
    @Override
    public ResponseData<Boolean> changeStatus(AdminDriverAbortParam abortParam) {
        DriverDto driverDto = new DriverDto();
        driverDto.setUuid(abortParam.getUuid());
        driverDto.setStatus(abortParam.getStatus());
        driverDto.setAbortTime(abortParam.getAbortTime());
        driverDto.setAbortRemark(abortParam.getAbortRemark());
        driverDto.setUpdateOn(new Date());
        driverDto.setUpdateBy(abortParam.getUserUuid());
        //解封操作
        if (abortParam.getStatus() == DriverConstant.DRIVER_STATUS_NORMAL) {
            return ResponseData.buildSuccessResponse(driverMapper.changeAccount(driverDto) > 0);
        }
        //封号操作
        try {
            DriverDto tempDto = driverMapper.get(abortParam.getUuid());
            if (tempDto != null) {
                Map<String, Object> params = MapUtils.build(4);
                params.put("driverUuid", abortParam.getUuid());
                params.put("appid", abortParam.getAppid());
                ResponseData<List<OrderDto>> doingOrder = orderRiskControlService.driverHasGoingOrder(params);
                if (doingOrder.isSuccess()) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机有进行中的订单，不能封号");
                }
                //下班收车
                if (DriverConstant.DRIVER_IS_WORK.equals(tempDto.getIsWork())) {
                    Double lng = 0d;
                    Double lat = 0d;
                    if (redisCacheService.get(MagicConstant.PARAMS_DRIVER_CURRENT_LNG + abortParam.getUuid()) != null) {
                        lng = (Double) redisCacheService.get("driverCurrentLng" + abortParam.getUuid());
                    }
                    if (redisCacheService.get(MagicConstant.PARAMS_DRIVER_CURRENT_LAT + abortParam.getUuid()) != null) {
                        lat = (Double) redisCacheService.get("driverCurrentLat" + abortParam.getUuid());
                    }
                    ResponseData<Boolean> offWork = offWork(abortParam.getUuid(), lng, lat, "");
                    if (!offWork.isSuccess()) {
                        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "收车失败，请重试");
                    }
                }
                //收车，需要传点
                if (DriverConstant.DRIVER_IS_WORK.equals(tempDto.getIsWork())) {
                    ResponseData<Boolean> offWorkPoint = locationService.copyLastPointAsOffWorkPoint(abortParam.getUuid());
                    //上传收车点失败，回滚事务
                    if (!offWorkPoint.isSuccess()) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "上传收车点经纬度失败，收车失败");
                    }
                }
                //清除缓存
                if (StringUtils.isNotEmpty(driverDto.getToken())) {
                    redisCacheService.delete(driverDto.getToken());
                }
                //推送长链接
                String serviceTel = ApplicationConfig.COMMON_CONFIG.getServiceTel();
                ResponseData<SysCompanyDto> getCompany = sysCompanyService.get(tempDto.getCompanyUuid());
                if (getCompany.isSuccess() && getCompany.getData() != null) {
                    serviceTel = getCompany.getData().getPhone();
                }
                String content = "账户已被管理员封号，封号原因：" + abortParam.getAbortRemark() + "，详情请查询客服电话：" + serviceTel;
                Map<String, Object> pushMap = MapUtils.build();
                pushMap.put("title", "司机封号");
                pushMap.put("content", content);
                PushContent pushContent = PushContent.newInstance4Dri(abortParam.getAppid(), PushContent.ORDER_DRIVER_SEAL_ACCOUNT, pushMap);
                pushService.sendMessage(abortParam.getUuid(), pushContent);
                //更新表数据
                driverMapper.changeAccount(driverDto);
                DriverPunishLogDto driverPunishLogDto = new DriverPunishLogDto();
                driverPunishLogDto.setUuid(StringUtils.buildUUID());
                driverPunishLogDto.setLicenseId(tempDto.getLicenseId());
                driverPunishLogDto.setDriverUuid(tempDto.getUuid());
                driverPunishLogDto.setPunishTime(new Date());
                driverPunishLogDto.setPunishReason(abortParam.getAbortRemark());
                driverPunishLogDto.setPunishResult(String.valueOf(abortParam.getStatus()));
                driverPunishLogService.add(driverPunishLogDto);
                return ResponseData.buildSuccessResponse("封号成功", Boolean.TRUE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "封号失败");

    }


    @Override
    public ResponseData<List<String>> getDriverUuidList(Map<String, Object> params) {
        return ResponseData.buildSuccessResponse(driverMapper.getDriverUuidList(params));
    }

    @Override
    public ResponseData<Map<String, Object>> getDriverInfo(String driverUuid) {
        //司机个人信息
        DriverVo driverVo = driverMapper.selInfoByTokenOrId(MapUtils.build("uuid", driverUuid));
        if (null == driverVo) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机个人信息");
        }
        driverVo.setFace(driverVo.getFace());
        //获取司机评价标签统计
        ResponseData<List<CommonEvaluateCountDto>> data = commonEvaluateCountService.findListByDriverUuid(driverUuid);
        Map<String, Object> dataMap = MapUtils.build();
        dataMap.put("userInfo", driverVo);
        if (data.isSuccess() && CollectionUtils.isNotEmpty(data.getData())) {
            List<CommonEvaluateCountDto> evaluateCountDtos = data.getData();
            dataMap.put("evaluateCount", evaluateCountDtos);
            return ResponseData.buildSuccessResponse("获取信息成功", dataMap);
        }
        return ResponseData.buildSuccessResponse(dataMap);
    }

    @Override
    public ResponseData<List<String>> filterWorkUuid(List<String> driverUuids) {
        Map<String, Object> doingMap = MapUtils.build(2);
        doingMap.put("orginalUuids", driverUuids);
        return ResponseData.buildSuccessResponse(driverMapper.filterWorkUuid(doingMap));
    }

    @Override
    public ResponseData<List<String>> filterAssignDriver(Map<String, Object> params) {
        List<String> driverUuidList = (List<String>) params.get("uniqueSortedDriverUuidList");
        if (CollectionUtils.isEmpty(driverUuidList)) {
            logger.info("orderUuid:{},无符合业务司机", params.get("orderUuid"));
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无符合业务司机");
        }
        logger.info("orderUuid:{},筛选前司机列表：{}", params.get("orderUuid"), JsonUtils.toJSONString(driverUuidList));
        List<String> filterUuidList = driverMapper.filterAssignDriver(params);
        if (filterUuidList.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到适合业务的司机");
        }
        return ResponseData.buildSuccessResponse("获取适合业务的司机成功", filterUuidList);
    }

    @Override
    public ResponseData<List<String>> filterGrabDriverReservation(String carModelValuationUuid, List<String> driverIdList,
                                                                  Date departTime, Integer remindType, Integer seatNum,
                                                                  String originCityUuid, boolean isStationOrder) {
        Map<String, Object> map = MapUtils.build(16);
        map.put("carModelValuationUuid", carModelValuationUuid);
        map.put("driverIdList", driverIdList);
        map.put("departTime", departTime.getTime());
        map.put("remindType", remindType);
        map.put("seatNum", seatNum);
        map.put("originCityUuid", originCityUuid);
        map.put("isStationOrder", isStationOrder);
        logger.info("查看预约订单参数" + map);
        return ResponseData.buildSuccessResponse(driverMapper.filterGrabDriverReservation(map));
    }


    @Override
    public ResponseData<List<String>> getTheSameCityDriver(String appid, Integer typeTrip, String originCityUuid) {
        Map<String, Object> params = MapUtils.build(5);
        params.put("appid", appid);
        params.put("type", typeTrip);
        params.put("cityUuid", originCityUuid);
        return ResponseData.buildSuccessResponse(driverMapper.getTheSameCityDriver(params));
    }


    @Override
    public ResponseData<List<String>> filterGrabDriver(String carModelValuationUuid, List<String> driverIdList,
                                                       boolean isSelf, Integer seatNum, String originCityUuid, boolean isStationOrder) {
        Map<String, Object> doingMap = MapUtils.build(3);
        doingMap.put("carModelValuationUuid", carModelValuationUuid);
        doingMap.put("driverIdList", driverIdList);
        doingMap.put("isSelf", isSelf);
        doingMap.put("seatNum", seatNum);
        doingMap.put("originCityUuid", originCityUuid);
        doingMap.put("isStationOrder", isStationOrder);
        return ResponseData.buildSuccessResponse(driverMapper.filterGrabDriver(doingMap));
    }

    @Override
    public ResponseData<DriverVo> commonSelInfo(Map<String, Object> map) {
        return ResponseData.buildSuccessResponse(driverMapper.selInfoByTokenOrId(map));
    }

    @Override
    public ResponseData<List<DriverDto>> getValidDriver(Map<String, Object> params) {
        params.put("dimission", DriverConstant.DRIVER_STATUS_DIMISSION);
        return ResponseData.buildSuccessResponse(driverMapper.getValidDriver(params));
    }

    @Override
    public ResponseData<Boolean> recordOnOrOffLine(String driverUuid, Long uploadDate) {
        logger.info("这里是司机id" + driverUuid);
//        DriverDto driverDto = driverMapper.list(MapUtils.build("uuid", driverUuid)).get(0);
        List<DriverDto> list = driverMapper.list(MapUtils.build("uuid", driverUuid));
        if (list.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到司机信息");
        }
        DriverDto driverDto = list.get(0);
        if (null == driverDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到司机信息");
        }
        Map<String, Object> params = MapUtils.build();
        params.put("driverUuid", driverUuid);
        params.put("active", DriverStatusCycleDto.ACTIVE_OFF);
        DriverStatusCycleDto driverStatusCycleDto = driverStatusCycleService.queryOne(params).getData();
        if (driverStatusCycleDto != null) {
            long time = 5 * 60 * 1000;
            //超出5分钟状态离线处理
            if (driverStatusCycleDto.getStatus() == DriverStatusCycleDto.EMPTY_RIDE && System.currentTimeMillis() - uploadDate > time) {
                orderTrackMileageService.statusCycle(driverDto.getAppid(), driverDto.getUuid(), null, driverDto.getCarUuid(), DriverStatusCycleDto.ACTION_OFF_LINE);
            }
            //恢复时间大于离线记录开始时间
            if (driverStatusCycleDto.getStatus() == DriverStatusCycleDto.OFF_LINE && driverStatusCycleDto.getStartTime().getTime() < uploadDate) {
                orderTrackMileageService.statusCycle(driverDto.getAppid(), driverDto.getUuid(), null, driverDto.getCarUuid(), DriverStatusCycleDto.ACTION_ON_LINE);
            }
        }
        return ResponseData.buildSuccessResponse("记录成功", Boolean.TRUE);
    }


    @Override
    public ResponseData<DriverDto> getDriverByIdCard(String idCard) {
        List<DriverDto> driverDtos = this.driverMapper.list(MapUtils.build("idCard", idCard));
        if (CollectionUtils.isNotEmpty(driverDtos)) {
            return ResponseData.buildSuccessResponse(driverDtos.get(0));
        }
        return ResponseData.buildSuccessResponse(null);
    }


    @Override
    public ResponseData<Boolean> statusSplit() {
        Map<String, Object> params = MapUtils.build();
        //未激活
        params.put("active", DriverStatusCycleDto.ACTIVE_OFF);
        //空驶状态
        params.put("status", DriverStatusCycleDto.EMPTY_RIDE);
        ResponseData<List<DriverStatusCycleDto>> listResponseData = driverStatusCycleService.queryByActive(params);
        if (listResponseData.isSuccess() && CollectionUtils.isNotEmpty(listResponseData.getData())) {
            List<DriverStatusCycleDto> statusCycleList = listResponseData.getData();
            for (DriverStatusCycleDto driverStatusCycleDto : statusCycleList) {
//                DriverDto driverDto = driverMapper.list(MapUtils.build("uuid", driverStatusCycleDto.getDriverUuid())).get(0);
                List<DriverDto> list = driverMapper.list(MapUtils.build("uuid", driverStatusCycleDto.getDriverUuid()));
                if (!list.isEmpty()) {
                    DriverDto driverDto = list.get(0);
                    if (null != driverDto) {
                        orderTrackMileageService.statusCycle(driverDto.getAppid(), driverDto.getUuid(), null, driverDto.getCarUuid(), DriverStatusCycleDto.ACTION_SPLIT);
                    }
                }
            }
        }
        return ResponseData.buildSuccessResponse("记录分割成功", Boolean.TRUE);
    }

    @Override
    public void incrDriOrderCountByUuid(String uuid) {
        driverMapper.incrDriOrderCountByUuid(uuid);
    }

    @Override
    @Transactional
    public ResponseData<Boolean> importDriver(List<DriverDto> driverDtoList, List<DriverTrainDto> driverTrainDtoList,
                                              List<DriverDto> updatingDriverDtoList, List<DriverTrainDto> updatingDriverTrainDtoList) {
        if (!driverDtoList.isEmpty()) {
            List<SysAccountDriverDto> accountDriverDtos = new ArrayList<>();
            for (DriverDto driverDto : driverDtoList) {
                // 设置唯一编号
                driverDto.setDriverUniqueId(DriverUniqueIdUtils.getDriverUniqueId(driverDto.getCityUuid()));
                //同步新增司机账户
                SysAccountDriverDto accountDriverEntity = new SysAccountDriverDto();
                accountDriverEntity.setUuid(driverDto.getUuid());
                accountDriverEntity.setAccountName(driverDto.getName());
                accountDriverEntity.setFrozenBalance(BigDecimal.ZERO);
                accountDriverEntity.setCanFrowardBalance(BigDecimal.ZERO);
                accountDriverEntity.setFrowardAccumulate(BigDecimal.ZERO);
                accountDriverEntity.setAlipayAccumulate(BigDecimal.ZERO);
                accountDriverEntity.setTenpayAccumulate(BigDecimal.ZERO);
                accountDriverEntity.setCreateOn(new Date());
                accountDriverDtos.add(accountDriverEntity);
            }
            driverMapper.addBatch(driverDtoList);
            sysAccountDriverService.saveBatch(accountDriverDtos);
        }
        if (!driverTrainDtoList.isEmpty()) {
            driverTrainMapper.addBatch(driverTrainDtoList);
        }
        if (!updatingDriverDtoList.isEmpty()) {
            driverMapper.updateBatch(updatingDriverDtoList);
        }
        if (!updatingDriverTrainDtoList.isEmpty()) {
            driverTrainMapper.importUpdateBatch(updatingDriverTrainDtoList);
        }
        return ResponseData.buildSuccessResponse("导入成功", Boolean.TRUE);
    }


    @Override
    public ResponseData<Boolean> driverDimission(AdminDriverDismissParam driverDimissParam) {
        DriverDto driverDto = driverMapper.get(driverDimissParam.getUuid());
        if (driverDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到司机信息");
        }
        ResponseData<List<OrderDto>> driverHasGoingOrder = orderRiskControlService.driverHasGoingOrder(
                MapUtils.build("driverUuid", driverDimissParam.getUuid()));
        if (driverHasGoingOrder.isSuccess() && CollectionUtils.isNotEmpty(driverHasGoingOrder.getData())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机有未完成订单，暂不能离职");
        }
        //司机离职清空车辆、代理、公司、合同等信息
        //备注曾经的申请信息
        Map<String, Object> map = new HashMap<>(4);
        map.put("mobile", driverDto.getMobile());
        map.put("type", driverDto.getBusinessType());
        List<DriverCheckDto> driverCheckDtos = driverCheckMapper.list(map);
        if (driverCheckDtos != null) {
            for (DriverCheckDto driverCheckDto : driverCheckDtos) {
                DriverCheckDto driverCheckParam = new DriverCheckDto();
                driverCheckParam.setUuid(driverCheckDto.getUuid());
                driverCheckParam.setMobile(driverDto.getMobile() + "(已离职)");
                driverCheckMapper.edit(driverCheckParam);
            }
        }
        driverDto.setCarUuid(null);
//        driverDto.setAgentUuid(null);
//        driverDto.setCompanyUuid(null);
        driverDto.setContractCompany(null);
        driverDto.setContractOff(null);
        driverDto.setContractOn(null);
        driverDto.setContractPhoto(null);
        driverDto.setContractSign(null);
        driverDto.setContractType(null);
        //离职
        driverDto.setStatus(DriverConstant.DRIVER_STATUS_DIMISSION);
        driverDto.setIsWork(1);
        driverDto.setUpdateOn(new Date());
        driverDto.setUpdateBy(driverDimissParam.getUserUuid());
        driverDto.setDimissionTime(new Date());
        driverDto.setDimissionRemark(driverDimissParam.getDimissionRemark());
        return ResponseData.buildSuccessResponse(driverMapper.driverDimission(driverDto) > 0);
    }


    @Override
    public ResponseData<List<DriverDto>> findDriverByMobileOrId(String mobile, String idCard) {
        return ResponseData.buildSuccessResponse(driverMapper.findDriverByMobileOrId(mobile, idCard));
    }

    @Override
    public ResponseData<String> getDriverServiceTel(String driverUuid, String companyUuid) {
        if (StringUtils.isEmpty(companyUuid)) {
            List<DriverDto> list = driverMapper.list(MapUtils.build("uuid", driverUuid));
            if (CollectionUtils.isNotEmpty(list)) {
                companyUuid = list.get(0).getCompanyUuid();
            }
        }
        if (StringUtils.isEmpty(companyUuid)) {
            return ResponseData.buildSuccessResponse(ApplicationConfig.COMMON_CONFIG.getServiceTel());
        }
        String serviceTel = ApplicationConfig.COMMON_CONFIG.getServiceTel();
        ResponseData<SysCompanyDto> getCompany = sysCompanyService.get(companyUuid);
        if (getCompany.isSuccess() && getCompany.getData() != null && StringUtils.isNotEmpty(getCompany.getData().getPhone())) {
            serviceTel = getCompany.getData().getPhone();
        }
        return ResponseData.buildSuccessResponse(serviceTel);
    }

    @Override
    public ResponseData<String> getDriverJoinServiceTel(String driverUuid, String companyUuid) {
        if (StringUtils.isEmpty(companyUuid)) {
            List<DriverDto> list = driverMapper.list(MapUtils.build("uuid", driverUuid));
            if (CollectionUtils.isNotEmpty(list)) {
                companyUuid = list.get(0).getCompanyUuid();
            }
        }
        if (StringUtils.isEmpty(companyUuid)) {
            return ResponseData.buildSuccessResponse(ApplicationConfig.SERVER_CONFIG.getSystem().getJoinServiceTel());
        }
        String serviceTel = ApplicationConfig.SERVER_CONFIG.getSystem().getJoinServiceTel();
        ResponseData<SysCompanyDto> getCompany = sysCompanyService.get(companyUuid);
        if (getCompany.isSuccess() && getCompany.getData() != null && StringUtils.isNotEmpty(getCompany.getData().getPhone())) {
            serviceTel = getCompany.getData().getPhone();
        }
        return ResponseData.buildSuccessResponse(serviceTel);
    }


    @Override
    public ResponseData<List<DriverSameWayInfoVo>> getSameWayDriverUuid(Integer businessType, List<String> driverUuids) {
        if (CollectionUtils.isEmpty(driverUuids)) {
            logger.warn("获取顺路模式司机为空");
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到开启顺路模式司机");
        }
        return ResponseData.buildSuccessResponse(driverMapper.getSameWayDriverUuid(businessType, driverUuids));
    }

    @Override
    public ResponseData<Boolean> closeDriverSameWayModel(String businessType) {
        driverMapper.closeDriverSameWayModel(businessType);
        return ResponseData.buildSuccessResponse("更新成功", true);
    }

    @Override
    public ResponseData<DriverRemindTypeVo> getDriverRemindType(String driverUuid) {
        DriverRemindTypeVo driverRemindTypeVo = driverMapper.getDriverRemindType(driverUuid);
        if (driverRemindTypeVo != null) {
            //顺路模式被允许时，则返回顺路相关信息
            if (getDriverSameWaySwitch(driverRemindTypeVo.getBusinessType())) {
                //获取司机允许顺路模式次数
                Integer allowSameWayCount = getDriverRemindTypeBean(driverRemindTypeVo.getBusinessType()).getSameWayOrderCount();
                //获取司机今日已接顺路次数
                Integer nowSameWayCount = driverMapper.queryDriverTodayOrder(driverUuid, 1);
                //剩余顺路次数
                driverRemindTypeVo.setSameWayResNum(allowSameWayCount - nowSameWayCount);
                //查询司机今日是否已完成首单
                Integer orderCount = driverMapper.queryDriverTodayOrder(driverUuid, null);
                driverRemindTypeVo.setCompleteFirstOrder(orderCount == 0 ? 0 : 1);
            }
            return ResponseData.buildSuccessResponse(driverRemindTypeVo);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到听单模式配置");
    }

    /**
     * 获取司机公司经营城市信息
     *
     * @param driverUuid
     * @return
     */
    @Override
    public ResponseData<List<DriverManageInfoVo>> getManageInfo(String driverUuid) {
        List<DriverManageInfoVo> list = driverMapper.getManageInfo(driverUuid);
        if (CollectionUtils.isNotEmpty(list)) {
            for (DriverManageInfoVo manageInfo : list) {
                //区域拼音为空 需要重新指定
                if (StringUtils.isEmpty(manageInfo.getManageNamePinyin())) {
                    manageInfo.setManageNamePinyin(PinyinUtils.covertPinyin(manageInfo.getManageName()));
                }
            }
            return ResponseData.buildSuccessResponse(list);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到经营城市信息");
    }

    /**
     * 获取司机允许顺利模式次数
     */
    private DriverConfig.OrderBean.RemindTypeBean.RemindTypeItmeBean getDriverRemindTypeBean(Integer businessType) {
        try {
            DriverConfig.OrderBean.RemindTypeBean remindTypeBean = ApplicationConfig.DRIVER_CONFIG.getOrder().getRemindType();
            switch (businessType) {
                case 1:
                    return remindTypeBean.getTaxi();
                case 2:
                    return remindTypeBean.getSpecial();
                case 4:
                    return remindTypeBean.getExpress();
                default:
                    return null;
            }
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取司机顺路模式开关
     */
    private boolean getDriverSameWaySwitch(Integer businessType) {
        try {
            DriverConfig.OrderBean.RemindTypeBean remindTypeBean = ApplicationConfig.DRIVER_CONFIG.getOrder().getRemindType();
            switch (businessType) {
                case 1:
                    return remindTypeBean.getTaxi().isSameWayModel();
                case 2:
                    return remindTypeBean.getSpecial().isSameWayModel();
                case 4:
                    return remindTypeBean.getExpress().isSameWayModel();
                default:
                    return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 关闭不接火车站订单
     *
     * @param businessType
     * @return
     */
    @Override
    public ResponseData<Boolean> closeDriverStationModel(String businessType) {
        driverMapper.closeDriverStationModel(businessType);
        return ResponseData.buildSuccessResponse("更新成功", true);
    }

    ;

    /**
     * 司机解绑车辆
     *
     * @param bindCarParam
     * @return
     */
    @Override
    public ResponseData<Boolean> unBindCar(AdminDriverBindCarParam bindCarParam) {
        DriverDto driverDto = driverMapper.get(bindCarParam.getUuid());
        if (driverDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机不存在");
        }
        if (StringUtils.isEmpty(driverDto.getCarUuid())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机未绑定车辆");
        }
        if (driverDto.getIsWork() != null && driverDto.getIsWork().equals(DriverConstant.DRIVER_IS_WORK)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机已出车，无法解绑车辆");
        }
        int count = driverMapper.unBindCar(driverDto.getUuid());
        if (count != 1) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "解绑失败");
        }
        //短信通知
        SendMessageUtils.unBingCarSend(commonSmsService, driverDto.getMobile(), driverDto.getAppid());
        return ResponseData.buildSuccessResponse("司机解绑车辆成功", Boolean.TRUE);
    }

    /**
     * 获取司机佣金配置
     */
    @Override
    public ResponseData<DriverCommissionConfigDto> getDriverCommissionConfig(String driverUuid) {
        DriverCommissionConfigDto driverCommissionConfigDto = driverCommissionConfigMapper.getDriverCommissionConfig(driverUuid);
        return ResponseData.buildSuccessResponse(driverCommissionConfigDto);
    }

    /**
     * 保存司机佣金配置
     */
    @Override
    public ResponseData<Boolean> saveDriverCommissionConfig(DriverCommissionConfigDto driverCommissionConfigDto) {
        int successNum = 0;
        if (StringUtils.isEmpty(driverCommissionConfigDto.getUuid())) {
            driverCommissionConfigDto.setUuid(StringUtils.buildUUID());
            successNum = driverCommissionConfigMapper.add(driverCommissionConfigDto);
        } else {
            successNum = driverCommissionConfigMapper.edit(driverCommissionConfigDto);
        }
        if (successNum == 1) {
            return ResponseData.buildSuccessResponse(true);
        } else {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存失败");
        }
    }

    /**
     * 获取扫码司机信息
     *
     * @param driverUuid
     * @return
     */
    @Override
    public ResponseData<ScanCodeDriverInfoVo> getScanCodeDriverInfo(String driverUuid) {
        return ResponseData.buildSuccessResponse(driverMapper.getScanCodeDriverInfo(driverUuid));
    }
}
